{# ----------------------------------------------------------------------------
 # SymForce - Copyright 2022, Skydio, Inc.
 # This source code is under the Apache 2.0 license found in the LICENSE file.
 # ---------------------------------------------------------------------------- #}

  {# Handwritten methods for Rot3 #}
  // Quaternion

  Eigen::Quaternion<Scalar> Quaternion() const {
    return Eigen::Quaternion<Scalar>(data_.data());
  }

  explicit Rot3(const Eigen::Quaternion<Scalar>& q) : Rot3(q.coeffs()) {}

  static Rot3 FromQuaternion(const Eigen::Quaternion<Scalar>& q) {
    return Rot3(q);
  }

  // Angle-axis

  Eigen::AngleAxis<Scalar> AngleAxis() const {
    return Eigen::AngleAxis<Scalar>(Quaternion());
  }

  explicit Rot3(const Eigen::AngleAxis<Scalar>& aa) : Rot3(Eigen::Quaternion<Scalar>(aa)) {}

  static Rot3 FromAngleAxis(const Eigen::AngleAxis<Scalar>& aa) {
    return Rot3(aa);
  }

  static Rot3 FromAngleAxis(const Scalar angle, const Vector3& axis) {
    return Rot3(Eigen::AngleAxis<Scalar>(angle, axis));
  }

  // Rotation matrix

  // Note: ToRotationMatrix is autogenerated below

  static Rot3 FromRotationMatrix(const Eigen::Matrix<Scalar, 3, 3>& mat) {
    return Rot3(Eigen::Quaternion<Scalar>(mat));
  }

  // Generate a random element in SO3
  template <typename Generator>
  static Rot3 Random(Generator& gen) {
    std::uniform_real_distribution<Scalar> dist(0.0, 1.0);
    // This cannot be combined into RandomFromUniformSamples(dist(gen), dist(gen), dist(gen)),
    // because the standard does not guarantee evaluation order of arguments,
    // meaning that we would get different results on different compilers.
    const auto dist0 = dist(gen);
    const auto dist1 = dist(gen);
    const auto dist2 = dist(gen);
    return RandomFromUniformSamples(dist0, dist1, dist2);
  }

  // Flip the quaternion if needed to give a positive real part (w).
  // This can be useful for comparing rotations where double cover is an issue.
  Rot3 ToPositiveReal() const {
    if (Data()[3] < 0) {
      return Rot3(-Data());
    } else {
      return Rot3(Data());
    }
  }
